package com.etong.frame.directive.checker.impl;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Size extends CheckerImpl {
	public final static String KEY_MIN = "min";
	public final static String KEY_MAX = "max";
	public final static String KEY_VALUE = "value";
	public final static Integer DEFAULT = null;
	protected Integer max = null;
	protected Integer min = null;
	protected Integer value = null;
	protected Sizer sizer;

	protected interface Sizer {
		boolean check(int size);
	}

	protected class Miner implements Sizer {
		public boolean check(int size) {
			return size >= min;
		}
	}

	protected class Maxer implements Sizer {
		public boolean check(int size) {
			return size <= max;
		}
	}

	protected class Betweener implements Sizer {
		public boolean check(int size) {
			return size <= max && size >= min;
		}
	}

	protected class Valuer implements Sizer {
		public boolean check(int size) {
			return value.equals(size);
		}
	}

	public Size() {
		super("@Size");
	}

	protected void clear() {
		min = null;
		max = null;
		value = null;
		sizer = null;
	}

	protected boolean buildAttribute(String attribute) {
		String regx = "(\\w+) *= *(\\d+) *,?";
		Pattern pattern = Pattern.compile(regx);
		Matcher matcher = pattern.matcher(attribute);
		while (matcher.find()) {
			String name = matcher.group(1);
			String value = matcher.group(2);
			if (KEY_MIN.equalsIgnoreCase(name)) {
				this.min = Integer.parseInt(value);
			} else if (KEY_MAX.equalsIgnoreCase(name)) {
				this.max = Integer.parseInt(value);
			} else if (KEY_VALUE.equalsIgnoreCase(name)) {
				this.value = Integer.parseInt(value);
			}
		}

		if (DEFAULT != min && DEFAULT != max) {
			this.sizer = new Betweener();
		} else if (DEFAULT != min) {
			this.sizer = new Miner();
		} else if (DEFAULT != max) {
			this.sizer = new Maxer();
		}

		// value直接覆盖 min 和 max
		if (DEFAULT != value) {
			this.sizer = new Valuer();
		}

		return true;
	}

	public Integer getMax() {
		return max;
	}

	public void setMax(Integer max) {
		this.max = max;
	}

	public Integer getMin() {
		return min;
	}

	public void setMin(Integer min) {
		this.min = min;
	}

	public Integer getValue() {
		return value;
	}

	public void setValue(Integer value) {
		this.value = value;
	}

	public boolean build(String expr) {
		clear();

		setName(expr);

		Pattern pattern = Pattern.compile("\\@Size\\((.*)\\)");
		Matcher matcher = pattern.matcher(expr);
		if (matcher.matches()) {
			buildAttribute(matcher.group(1));
		}

		return DEFAULT != min || DEFAULT != max;
	}

	boolean checkSize(Map<?, ?> map) {
		return sizer.check(map.size());
	}

	public boolean check(Object object) {
		if (object instanceof Collection) {
			return checkSize(((List<?>) object));
		} else if (object instanceof Map) {
			return checkSize((Map<?, ?>) object);
		} else if (object instanceof String) {
			return checkLength((String) object);
		}
		return false;
	}

	private boolean checkLength(String object) {
		return sizer.check(object.length());
	}

	private boolean checkSize(List<?> list) {
		return sizer.check(list.size());
	}
}
